package com.wanmait.zaisousuo.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wanmait.zaisousuo.exception.ArticleNotFoundException;
import com.wanmait.zaisousuo.mapper.*;
import com.wanmait.zaisousuo.pojo.ArticleCollect;
import com.wanmait.zaisousuo.pojo.Question;
import com.wanmait.zaisousuo.pojo.Userinfo;
import com.wanmait.zaisousuo.service.ArticleService;
import com.wanmait.zaisousuo.service.UserinfoService;
import com.wanmait.zaisousuo.util.Pager;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.wanmait.zaisousuo.pojo.Article;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {

    @Resource(name = "articleSolrClient")
    private HttpSolrClient client;

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private ArticleCommentMapper articleCommentMapper;

    @Resource
    private ArticleCollectMapper articleCollectMapper;

    @Resource
    private ArticlePraiseMapper articlePraiseMapper;

    @Resource
    private UserinfoMapper userinfoMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public void insert(Article object) {

    }

    @Override
    public void update(Article object) {

    }

    @Override
    public void delete(Integer id) {

    }

    @Override
    public void delete(String ids) {

    }

    //根据文章id，查询出文章的所有详细信息
    @Cacheable(value = "ArticleCache",key = "'findByArticleId'+#id")
    @Override
    public Article findById(Integer id) {
        Article article = articleMapper.findById(id);
        if(article==null){
            throw new ArticleNotFoundException(id);
        }
        Integer praiseCount;
        try {
            praiseCount = Integer.parseInt((String) redisTemplate.opsForValue().get("article:" + id + ":praise:count"));
        }catch (Exception e) {
             praiseCount=0;
        }
        article.setPraiseCount(praiseCount);
        return article;
    }

    @Override
    public List<Article> findAll() {
        //return articleMapper.findAll();
        return null;
    }

    //根据用户id查文章
    //@Cacheable(value = "ArticleCache",key ="'findByUserId'+#id+'id='+#pageNum")
    @Override
    public PageInfo<Article> findById(Integer pageNum,Integer id) {
        int pageSize=10;
        PageHelper.startPage(pageNum,pageSize);
        List<Article> articles = articleMapper.findByUserId(id);
        PageInfo<Article> pageInfo = new PageInfo<>(articles,5);
        return pageInfo;
    }

    //可以根据时间范围搜索出文章
    //(清缓存：禁止启用、评论)
    @Cacheable(value = "ArticleCache",key = "'findAllArticleByTime'+#startTime+#endTime")
    @Override
    public List<Article> findAllByTime(String startTime, String endTime) {
        return articleMapper.findAll(startTime,endTime);
    }

    //后台更改文章的disabled状态
    @Override
    public Boolean changeDisabled(Boolean flag,Integer articleId) {
        articleMapper.updatechangeDisabled(flag,articleId);
        return flag;
    }

    //点赞
    @Override
    public Boolean parise(Integer id,Integer userinfoId)
    {
       Boolean flag = redisTemplate.opsForSet().isMember("article:"+id+":praise:"+userinfoId+":set",userinfoId+"");
       if (flag==false)
       {
           redisTemplate.opsForValue().increment("article:"+id+":praise:count",1);
           redisTemplate.opsForSet().add("article:"+id+":praise:"+userinfoId+":set",userinfoId+"");
           redisTemplate.opsForList().leftPush("article:praise:list","{articleId:"+id+",userinfoId:"+userinfoId+"}");
           redisTemplate.opsForSet().add("article:praise:set",id+"");
           return flag;
       }
       else {
            return flag;
       }
    }

    //收藏
    @Override
    public Boolean collect(Integer id,Integer userinfoId,String articleName,String authorName)
    {
        Boolean flag = redisTemplate.opsForSet().isMember("article:"+id+":collect:userinfo:set",userinfoId+"");
        if(flag==false)//没点收藏,去收藏
        {
            redisTemplate.opsForValue().increment("article:"+id+":collect:count:",1);//收藏数+1
            redisTemplate.opsForSet().add("article:"+id+":collect:userinfo:set",userinfoId+"");//set记录收藏文章id和用户id
            redisTemplate.opsForList().leftPush("article:collect:list","{articleId:"+id+",userinfoId:"+userinfoId+"}");//用于弹出同步到article_collect表
            redisTemplate.opsForSet().add("article:collect:set",id+"");//存放上次收藏数量同步之后，又被收藏的文章id
            redisTemplate.opsForSet().add("UserId:"+userinfoId,"{articleId:"+id+",title:'"+articleName+"',author:'"+authorName+"'}");//用于个人中心：我的收藏
        }
        if(flag==true)//点收藏，取消收藏
        {
            redisTemplate.opsForValue().increment("article:"+id+":collect:count:",-1);//收藏数-1
            redisTemplate.opsForSet().remove("article:"+id+":collect:userinfo:set",userinfoId+"");//set记录收藏文章id和用户id:删除
            redisTemplate.opsForList().remove("article:collect:list",0,"{articleId:"+id+",userinfoId:"+userinfoId+"}");//从中删除
            redisTemplate.opsForList().leftPush("article:delete:list","{articleId:"+id+",userinfoId:"+userinfoId+"}");//存放需要去数据库删除的收藏记录
            redisTemplate.opsForSet().remove("UserId:"+userinfoId,"{articleId:"+id+",title:'"+articleName+"',author:'"+authorName+"'}");//用于个人中心：我的收藏
        }
        return flag;
    }

    @Override
    public void updatePraiseCount(Integer praiseCount,Integer id) {
        articleMapper.updatePraiseCount(praiseCount,id);
    }

    @Override
    public void updateCollectCount(List<Article> articles){
        articleMapper.updateCollectCount(articles);
    }



    @Override
    public List<Article> findAll(Article object) {
        return null;
    }

    @Override
    public int getDataCount() {
        return 0;
    }

    @Override
    public int getDataCount(Article object) {
        return 0;
    }

    @Override
    public PageInfo<Article> findList(int pageNum) {
        return null;
    }


    //多条件搜索文章
    //(清缓存：禁止启用、评论)
    @Cacheable(value = "ArticleCache",key = "'findAllByConditions'+#typeId+#textId+#orderBy+#pageNum")
    @Override
    public PageInfo<Article> findAllByConditions(Integer typeId, Integer textId,String orderBy,Integer pageNum) {
        int pageSize=10;
        PageHelper.startPage(pageNum,pageSize);
        List<Article> articles = articleMapper.findAllByConditions(typeId,textId,orderBy);
        PageInfo pageInfo = new PageInfo<>(articles);
        return pageInfo;
    }

    //文章提交写入数据库
    @Override
    public void addOneArticle(Article article) {
        articleMapper.insert(article);
        userinfoMapper.publishedCountIncrease(article.getUserinfo().getId());
    }




    //删除文章以及与文章相关联的内容
    @Override
    public void deleteArticleAndRelative(Integer articleId) {
        //删除相关评论
        articleCommentMapper.deleteRelativeComments(articleId);
        //删除相关点赞
        articleCollectMapper.deleteRelativeCollects(articleId);
        //删除相关收藏
        articlePraiseMapper.deleteRelativePraises(articleId);
        //删除文章
        articleMapper.deleteByPrimaryKey(articleId);

    }


    //获取solr查询出来的数据总数
    @Override
    public Integer getDataCount(String solrsearch) {
        Integer dataCount=null;
        SolrQuery query=new SolrQuery();
        query.setQuery("title:"+solrsearch);
        QueryResponse response=null;
        try {
            response=client.query(query);
            SolrDocumentList documentList=response.getResults();
            dataCount=(int)documentList.getNumFound();
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataCount;
    }



    //solr查询文章
    @Override
    public List<Article> findArticlesBySolr(String solrsearch,Integer pageNum, Pager pager){
        SolrQuery query = new SolrQuery();

        //设置查询的条件
        query.setQuery("title:"+solrsearch);
        //设置高亮为true
        //设置高亮字段
        query.setHighlight(true);
        query.set("hl.fl","title");
        //分页
        query.setStart((pager.getPageNum()-1)*pager.getPageSize());
        query.setRows(pager.getPageSize());
        //设置高亮的颜色
        query.setHighlightSimplePre("<em style=\"color:red\">");
        query.setHighlightSimplePost("</em>");
        //查询结果
        QueryResponse response = null;
        List<Article> articles = new ArrayList<>();
        Article article = null;

        try {
             response = client.query(query);

            SolrDocumentList documentList = response.getResults();

            //获得高亮数据 外层的map的键为id 内侧的map的键为高亮字段title
            Map<String, Map<String, List<String>>> highLighting = response.getHighlighting();
            String id="";
            for (SolrDocument document : documentList) {
                id = (String) document.getFieldValue("id");

                article = new Article();
                article.setId(Integer.parseInt((String) document.getFieldValue("id")));//自增长id
                article.setTitle((String)highLighting.get(id).get("title").get(0));//高亮显示：文章标题

                Userinfo userinfo = new Userinfo();
                userinfo.setId(Integer.parseInt((String)document.getFieldValue("userinfoId")));//用户id
                userinfo.setNickname((String)document.getFieldValue("nickname"));//用户昵称
                article.setUserinfo(userinfo);

                article.setPraiseCount(Integer.parseInt((String)document.getFieldValue("praiseCount")));//点赞数
                article.setCollectCount(Integer.parseInt((String)document.getFieldValue("collectCount")));//收藏数

                articles.add(article);
            }
        }
        catch (IOException E){}
        catch (NullPointerException e){return articles;}
        catch (SolrServerException e){}

        return articles;
    }


    //根据用户id去redis里面查询出收藏的文章
    @Override
    public List<Article> findCollectByUserId(Integer userId) {
        Set set = redisTemplate.opsForSet().members("UserId:"+userId);
        List<Article> articles = new ArrayList<>();
        Article article = null;
        Userinfo userinfo = null;
        for (Object o:set){
            JSONObject jsonObject = JSONObject.parseObject(o.toString());

            article = new Article();
            article.setTitle(jsonObject.get("title").toString());
            article.setId(Integer.parseInt(jsonObject.get("articleId").toString()));

            userinfo = new Userinfo();
            userinfo.setNickname(jsonObject.get("author").toString());
            article.setUserinfo(userinfo);

            articles.add(article);
        }
        return articles;
    }


    //清除ehcache全部缓存：ArticleCache
    @CacheEvict(value = "ArticleCache",allEntries = true)
    @Override
    public void clearCache() {
    }

    //点赞、收藏清除:根据id查文章缓存
    @CacheEvict(value = "ArticleCache",key = "'findByArticleId'+#id")
    @Override
    public void clearQuerybyidCache(Integer id){}

    /*//发表文章、后台禁用、删除文章清除：根据用户id查找文章缓存
    @CacheEvict(value = "ArticleCache",key ="'findByUserId'+#id+'id=*'")
    @Override
    public void clearQuerybyuserCache(Integer id){}*/


}
